/*
 * Copyright (c) 2007-2008, Thomas Krause (tho.krause@gmail.com)
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *     * Neither the name of gidoo nor the names of its contributors may be used to
 *       endorse or promote products derived from this software without specific
 *       prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.gidoo.cms.editor.structure;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.gidoo.cms.GidooCMS;
import org.gidoo.cms.editor.EditorPage;
import org.gidoo.cms.jcr.JcrHelper;
import org.gidoo.cms.login.GidooCMSSession;

/**
 *
 * @author thomas
 */
public class StructurePanel extends Panel
{

  private Form mainForm;
  private TextField txtNewFolderName;
  private AjaxButton btAdd;
  private AjaxButton btDelete;
  private AjaxButton btUp;
  private AjaxButton btDown;
  private AjaxButton btCut;
  private AjaxButton btPaste;
  private TextField txtRename;
  private AjaxButton btRename;
  
  private EditorPage parentPage;
  
  private String thePagePath;
  
  public StructurePanel(String id, Node page, EditorPage parent)
  {
    super(id);
    
    try
    {

      this.parentPage = parent;   
      if(page == null)
      {
        this.thePagePath = null;
      }
      else
      {
        this.thePagePath = page.getPath();
      }
      mainForm = new Form("mainForm");

      btUp = new AjaxButton("btUp") {

        @Override
        protected void onSubmit(AjaxRequestTarget target, Form form)
        {
          folderUp();
          target.addComponent(parentPage.getFeedbackPanel());
          target.addComponent(parentPage.getTreeNav());
          target.addComponent(parentPage.getPanelTabs());
        }
      };
      btUp.setModel( new Model(getString("up")));
      mainForm.add(btUp);
      
      btDown = new AjaxButton("btDown"){

        @Override
        protected void onSubmit(AjaxRequestTarget target, Form form)
        {
          folderDown();
          target.addComponent(parentPage.getFeedbackPanel());
          target.addComponent(parentPage.getTreeNav());
          target.addComponent(parentPage.getPanelTabs());
        }
      };
      btDown.setModel(new Model(getString("down")));
      mainForm.add(btDown);
      
      txtNewFolderName = new TextField("txtNewFolderName", new Model(""));
      mainForm.add(txtNewFolderName);

      btAdd = new AjaxButton("btAdd")
      {
        @Override
        protected void onSubmit(AjaxRequestTarget target, Form form)
        {
          addFolder();
          target.addComponent(parentPage.getFeedbackPanel());
          target.addComponent(parentPage.getTreeNav());
        }
        
      };
      
      btAdd.setModel(new Model(getString("add")));
      mainForm.add(btAdd);

      btDelete = new AjaxButton("btDelete") {


        @Override
        protected void onSubmit(AjaxRequestTarget target, Form form)
        {
          deleteFolder();
          target.addComponent(parentPage.getFeedbackPanel());
          target.addComponent(parentPage.getTreeNav());
        }
      };
      btDelete.setModel(new Model(getString("delete")));
      mainForm.add(btDelete);

      btCut = new AjaxButton("btCut") {

        @Override
        protected void onSubmit(AjaxRequestTarget target, Form form)
        {
          cut();
          target.addComponent(parentPage.getFeedbackPanel());
        }
      };
      btCut.setModel(new Model(getString("cut")));
      
      btCut.setEnabled(page != null &&
        !"cms:section".equals(page.getPrimaryNodeType().getName()));
      
      mainForm.add(btCut);
      
      btPaste = new AjaxButton("btPaste") {

        @Override
        protected void onSubmit(AjaxRequestTarget target, Form form)
        {
          paste();
          
          target.addComponent(parentPage.getFeedbackPanel());
          target.addComponent(parentPage.getTreeNav());
          target.addComponent(parentPage.getPanelTabs());
        }
      };
      btPaste.setModel(new Model(getString("paste")));
      
      btPaste.setEnabled(
        page != null &&
        parentPage.getLastCutPath() != null 
        && !parentPage.getLastCutPath().equals(page.getPath()));
      
      mainForm.add(btPaste);
      
      txtRename = new TextField("txtRename", new Model(""));
      txtRename.setEnabled(page != null && 
        !"cms:section".equals(page.getPrimaryNodeType().getName()));
      mainForm.add(txtRename);
      
      btRename = new AjaxButton("btRename") {

        @Override
        protected void onSubmit(AjaxRequestTarget target, Form form)
        {
          rename();
          target.addComponent(parentPage.getFeedbackPanel());
          target.addComponent(parentPage.getTreeNav());
          target.addComponent(parentPage.getPanelTabs());
          
        }
      };      
      btRename.setModel(new Model(getString("rename")));
      btRename.setEnabled(page != null &&
        !"cms:section".equals(page.getPrimaryNodeType().getName()));
      mainForm.add(btRename);
      
      add(mainForm);

      if(page == null)
      {
        mainForm.setVisible(false);
      }
      else if("cms:section".equals(page.getPrimaryNodeType().getName()))
      {
        btDelete.setVisible(false);
      }
    }
    catch(RepositoryException ex)
    {
      error("jcrerror");
    }

  }

  private void rename()
  {
    
    Session session = ((GidooCMSSession) getSession()).getJcrSession();
    
    
    try
    {
      Node page = session.getRootNode().getNode(thePagePath.substring(1));
      String newName = txtRename.getModelObjectAsString();
      Node parent = page.getParent();

      if(newName == null || "".equals(newName))
      {
        error(getString("namewasnull"));
      }
      else if("cms:section".equals(page.getPrimaryNodeType().getName()))
      {
        error(getString("sectionnotallowed"));
      }
      else if(newName.contains("/"))
      {
        error(getString("noslashallowed"));
      }
      else
      {
          // check if already existant
          NodeIterator it = parent.getNodes();
          while(it.hasNext())
          {
            Node n = it.nextNode();
            if(n.getName().equals(newName))
            {
              error(getString("alreadyexists"));
              return;
            }
          }
          
          String oldPath = page.getPath();
          session.move(page.getPath(), parent.getPath() + "/" + newName);
          session.save();
          thePagePath = page.getPath();
          
          Logger.getLogger(GidooCMS.ACTION_LOGGER).log(Level.INFO, 
            "user \"" + ((GidooCMSSession) getSession()).getUsername() + 
            "\" renamed page from " + oldPath + " to " + thePagePath);
        }
      
        parentPage.updateDataAndView(page);
    }
    catch (RepositoryException ex)
    {
      Logger.getLogger(StructurePanel.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));
      parentPage.updateDataAndView();
    }
  }
  
  private void cut()
  {
    try
    {
      Session session = ((GidooCMSSession) getSession()).getJcrSession();
      Node page = session.getRootNode().getNode(thePagePath.substring(1));

      if("cms:section".equals(page.getPrimaryNodeType().getName()))
      {
        error(getString("sectionnotallowed"));
        return;
      }
      parentPage.setLastCutPath(thePagePath);
      info(getString("wascutted"));
    }
    catch(RepositoryException ex)
    {
      Logger.getLogger(StructurePanel.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));
    }
  }
  
  private void paste()
  {
    if(parentPage.getLastCutPath() != null)
    {
      try
      {
        Session session = ((GidooCMSSession) getSession()).getJcrSession();
        Node pageToMove = 
          session.getRootNode().getNode(parentPage.getLastCutPath().substring(1));
        Node currentPage = session.getRootNode().getNode(thePagePath.substring(1));
        
        parentPage.setLastCutPath(null);
        
        if("cms:section".equals(pageToMove.getPrimaryNodeType().getName()))
        {
          error(getString("sectionnotallowed"));
          return;
        }
        
        Node oldSection = JcrHelper.getSectionOfNode(session.getRootNode(), pageToMove);
        Node newSection = JcrHelper.getSectionOfNode(session.getRootNode(), currentPage);
        
        if(!oldSection.getName().equals(newSection.getName()))
        {
          error(getString("nooverlappaste"));
          return;
        }
        
        if(thePagePath.equals(parentPage.getPath()))
        {
          return;
        }
        
        String oldPath = pageToMove.getPath();
        session.move(pageToMove.getPath(), thePagePath + "/" + pageToMove.getName());
        session.save();
        parentPage.updateDataAndView(pageToMove);
        
        Logger.getLogger(GidooCMS.ACTION_LOGGER).log(Level.INFO,
          "user \"" + ((GidooCMSSession) getSession()).getUsername() + 
          "\" moved page " + oldPath + " to " + thePagePath);
        
        info(getString("moved"));
      }
      catch (RepositoryException ex)
      {
        Logger.getLogger(StructurePanel.class.getName()).log(Level.SEVERE, null, ex);
        error(getString("jcrerror"));
      }
      
    }
  }
  
  private void addFolder()
  {
    if(thePagePath == null)
    {
      warn(getString("null"));
      return;
    }

    String name = txtNewFolderName.getModelObjectAsString();
    if(name != null && !"".equals(name))
    {
      try
      {
        Node rootNode = ((GidooCMSSession) getSession()).getJcrRootNode();
        Node parent = rootNode.getNode(thePagePath.substring(1));
        
        // check for unallowed characters
        if(name.contains("/"))
        {
          error(getString("noslashallowed"));
          return;
        }
        
        // check if already existant
        NodeIterator it = parent.getNodes();
        while(it.hasNext())
        {
          Node n = it.nextNode();
          if(n.getName().equals(name))
          {
            error(getString("alreadyexists"));
            return;
          }
        }
      
        // construct a new Folder
        Node p = parent.addNode(name, "cms:page");
        p.setProperty("cms:editor", ((GidooCMSSession) getSession()).getUsername());
        
        parent.save();

      }
      catch(RepositoryException ex)
      {
        Logger.getLogger(StructurePanel.class.getName()).log(Level.SEVERE, null, ex);
        error(getString("jcrerror"));
      }
    }
    else
    {
      error(getString("namewasnull"));
    }
    
    parentPage.updateDataAndView();
    
  }

  private void deleteFolder()
  {
    Node toSelect = parentPage.getCurrentSelectedPage();
      
    try
    {
      if(thePagePath == null)
      {
        warn(getString("null"));
        return;
      }
      
      Node root = ((GidooCMSSession) getSession()).getJcrRootNode();
      Node page = root.getNode(thePagePath.substring(1));
      
      if("cms:section".equals(page.getPrimaryNodeType().getName()))
      {
        error(getString("sectionnotallowed"));
      }      
      else if(page.hasNodes())
      {
        error(getString("nosubpagesallowed"));
      }
      else
      {
        Node parent = page.getParent();
        
        boolean pageEmpty = true;
        if(page.hasProperty("cms:xml") && 
          !page.getProperty("cms:xml").getString().equals(""))
        {
          pageEmpty = false;
        }
        if(page.hasProperty("cms:title") && 
          !page.getProperty("cms:title").getString().equals(""))
        {
          pageEmpty = false;
        }
        if(pageEmpty)
        {
          String oldPath = page.getPath();
          page.remove();
          parent.save();
          
          Logger.getLogger(GidooCMS.ACTION_LOGGER).log(Level.INFO, 
            "user \"" + ((GidooCMSSession) getSession()).getUsername() + 
            "\" deleted page " + oldPath);
          
          toSelect = parent;
        }
        else
        {
          error(getString("pagemustbeemptybeforedelete"));
        }
      }
    }
    catch(RepositoryException ex)
    {
      Logger.getLogger(StructurePanel.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));
    }
    
    parentPage.updateDataAndView(toSelect);
    
  }
  
  private void folderDown()
  {
    if(thePagePath == null)
      return;
    
    try
    {
      Session session = ((GidooCMSSession) getSession()).getJcrSession();
      Node page = session.getRootNode().getNode(thePagePath.substring(1));
      
      if("cms:section".equals(page.getPrimaryNodeType().getName()))
      {
        error(getString("sectionnotallowed"));
        return;
      }
      
      Node parent = page.getParent();
      NodeIterator it = parent.getNodes();
      
      while (it.hasNext())
      {
        Node c = it.nextNode();
        if(c.getName().equals(page.getName()))
        {
          Node nextCMSNode = null;
          while(it.hasNext())
          {
            Node n = it.nextNode();
            if("cms:page".equals(n.getPrimaryNodeType().getName()))
            {
              nextCMSNode = n;
              break;
            }
          }
          if(nextCMSNode != null)
          {
            parent.orderBefore(nextCMSNode.getName(), page.getName());
            parent.save();
          }
          break;
        }
      }
    }
    catch (RepositoryException ex)
    {
      Logger.getLogger(StructurePanel.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));

    }
    
    parentPage.updateDataAndView();
  }
  
  private void folderUp()
  {
    if(thePagePath == null)
      return;
    
    try
    {
      Session session = ((GidooCMSSession) getSession()).getJcrSession();
      Node page = session.getRootNode().getNode(thePagePath.substring(1));
      
      if("cms:section".equals(page.getPrimaryNodeType().getName()))
      {
        error(getString("sectionnotallowed"));
        return;
      }
      
      Node parent = page.getParent();
      NodeIterator it = parent.getNodes();
      
      Node lastNode = null;
      
      while (it.hasNext())
      {
        Node c = it.nextNode();
        if(c.getName().equals(page.getName()))
        {
          if(lastNode != null)
          {
            parent.orderBefore(page.getName(), lastNode.getName());
            parent.save();
          }
          break;
        }
        else if("cms:page".equals(c.getPrimaryNodeType().getName()))
        {
          lastNode = c;
        }
      }
    }
    catch (RepositoryException ex)
    {
      Logger.getLogger(StructurePanel.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));

    }
    
    parentPage.updateDataAndView();
  }

}
